﻿using ES.EsEntity;
using Nest;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ES
{
    public class ElasticBase
    {
        private static readonly Lazy<ElasticBase> lazy = new Lazy<ElasticBase>(() => new ElasticBase());
        private IElasticClient EsClient;
        public ElasticBase()
        {
            EsClient = ElasticSearchConfig.EsClient;
        }

        public static ElasticBase Instance
        {
            get
            {
                return lazy.Value;
            }
        }

        /// <summary>
        /// 创建索引并设置别名
        /// </summary>
        /// <returns></returns>
        public string CreateIndex()
        {
            //EsClient.IndexMany<PolicyInfo>(policyInfos, "policyInfos");
            //CreateIndex 创建索引，mapping  映射 
            var response = EsClient.CreateIndex("policyinfos",seting=>seting
            .Settings(setting => setting.NumberOfShards(3).NumberOfReplicas(1))//指定了该索引的分片数为3、副本数为1
             .Mappings(m => m.Map<PolicyInfo>(map => map.AutoMap())));//映射创建type
            if (!response.Acknowledged)
            {
                return "创建索引失败" + response.ServerError.Error.Reason;
            } 
            return "创建索引并设置别名成功！";
        }


        /// <summary>
        /// 删除索引
        /// </summary>
        /// <returns></returns>
        public string DeleteIndex()
        {
            //删除指定索引所在节点下的所有索引 
            var descriptor = new DeleteIndexDescriptor("policyinfos");     
            var index = EsClient.DeleteIndex(descriptor);
            if (index.IsValid)
            {
                return "删除索引成功";
            }
            return "删除索引失败";
        }


        /// <summary>
        /// 批量添加文档
        /// </summary>
        /// <returns></returns>
        public bool AddDocumentBulk()
        {
            var result = EsClient.IndexMany<PolicyInfo>(GetList(), "policyinfos");//批量增加文档   policyinfos 索引必须为小写
            return result.IsValid;
        }

        public string UpdateDocument()
        { 
            //跟新id等于4的数据
            PolicyInfo policyInfo = new PolicyInfo();
            policyInfo.Contents = "535345";
            policyInfo.Title = "2";
            policyInfo.id = 4;

            ///1 局部更新
            //IUpdateRequest<PolicyInfo, PolicyInfo> request = new UpdateRequest<PolicyInfo, PolicyInfo>(new DocumentPath<PolicyInfo>(4))
            //{
            //    Doc = new PolicyInfo
            //    {
            //        Title = "2"
            //    }
            //};
            //var update = EsClient.Update<PolicyInfo>(request);

            /// 2 局部更新
            //DocumentPath<PolicyInfo> deletePath = new DocumentPath<PolicyInfo>(4).Index("policyinfos"); ;
            //var response = EsClient.Update(deletePath, (p) => p.Doc(policyInfo));
            ///3 指定更新
            var response = EsClient.Update<PolicyInfo, object>(4, upt => upt.Doc(new { Title = "江山美人1" }).Index("policyinfos"));
            if (response.IsValid)
            {
                return "更新成功";
            }
            return "更新失败";
        }


        /// <summary>
        /// 删除文档（单条）
        /// </summary>
        /// <returns></returns>
        public string DeleteDocument(int id)
        {
            //DocumentPath<VendorPriceInfo> deletePath = new DocumentPath<VendorPriceInfo>(7);
            //client.Delete(deletePath); 

            //IDeleteRequest request = new DeleteRequest("test3", "vendorpriceinfo", 0);
            //client.Delete(request); 

            try
            {
                DocumentPath<PolicyInfo> deletePath = new DocumentPath<PolicyInfo>(id).Index("policyinfos"); 
                var index = EsClient.Delete(deletePath);
                if (index.IsValid)
                {
                    return "删除文档成功";
                }
            }
            catch (Exception ex)
            {
                string e = ex.ToString();
            }
            return "删除文档失败";
        }

        //批量更新
        public string UpdateDocumentBulk()
        {
            var ids = new List<int>() {4,5};
            var bulkQuest = new BulkRequest("policyinfos") { Operations = new List<IBulkOperation>() };
            foreach (var v in ids)
            {
                var operation = new BulkUpdateOperation<PolicyInfo, object>(v);
                operation.Doc = new { Title = "胡一刀" };
                bulkQuest.Operations.Add(operation);
            }
            var result = EsClient.Bulk(bulkQuest);
            if (result.IsValid)
            {
                return "更新成功";
            }
            return "更新失败";
        }


        /// <summary>
        /// 批量删除
        /// </summary>
        /// <returns></returns>
        public string DeleteDocumentBulk()
        { 
            var ids = new List<int>() { 2, 3};
            var bulkQuest = new BulkRequest("policyinfos") { Operations = new List<IBulkOperation>() };
            foreach (var v in ids)
            {
                bulkQuest.Operations.Add(new BulkDeleteOperation<PolicyInfo>(v));
            } 
            var result =EsClient.Bulk(bulkQuest);
            if (result.IsValid)
            {
                return "批量删除成功";
            }
            return "批量删除失败";
        }

        /// <summary>
        /// 查询所有
        /// </summary>
        /// <returns></returns>
        public List<PolicyInfo> GetAll()
        {
            var searchResults = EsClient.Search<PolicyInfo>(s => s.Index("policyinfos")
                .From(0)
                .Size(10000)
                );
            return searchResults.Documents.ToList();
        }

    


        /// <summary>
        /// 查询索引数据
        /// </summary>
        /// <param name="doctorId"></param>
        /// <returns></returns>
        public List<PolicyInfo> QueryDoctors(string key)
        {
            SearchDescriptor<PolicyInfo> searchDescriptor = new SearchDescriptor<PolicyInfo>().Index("policyinfos");
            //searchDescriptor.Query(q => q.Term(t => t.Field("id").Value(doctorId)));
            //          searchDescriptor.Query(q =>
            //  q.Bool(b => b.Must(m =>
            //m.MultiMatch(t => t.Fields(f => f.Field(obj => obj.Title)).Query(key)))));

          //  searchDescriptor.Query(q=>q.Match(m=>m.Field(f=>f.Title).Query(key))).From(0).Size(8);

            //全文搜索
            //searchDescriptor.Query(q => q.QueryString(qs => qs.Query(key).DefaultOperator(Operator.And)));

            //searchDescriptor.Query(m=>m.QueryString(b=>b.Fields(f=>f.Field(d=>d.Title)).Query(key))).From(0).Size(8);
            //searchDescriptor.Query(q => q.QueryString(m => m.Fields(fd => fd.Field(fdd => fdd.Title).Field(fdd => fdd.Title))
            //              .Query(key))).From(0).Size(15);


            //完全匹配
            // searchDescriptor.Query(m => m.Term(b => b.Field(v => v.Title).Value(key)));

            //过滤标题等于“长沙”或者等于“科技”的文档，匹配多个 中间用空格隔开
            // searchDescriptor.PostFilter(x => x.QueryString(t => t.Fields(f => f.Field(obj => obj.Title)).Query(" 长沙 科技")));

            //全文搜索
            //var searchResults = EsClient.Search<PolicyInfo>(s => s
            //    .Index("policyinfos").Query(q => q.QueryString(qs => qs.Query(key).DefaultOperator(Operator.And)))
            //    );
            //短语搜索  MatchPhrase 精确搜索
          // searchDescriptor.Query(q => q.MatchPhrase(m => m.Field(f => f.Title).Query(key))).From(0).Size(15);
            //多字段匹配 两个字段进行匹配，其中一个字段有这个文档就满足的话，使用multi_match
            // searchDescriptor.Query(q => q.MultiMatch(m => m.Fields(fd => fd.Fields(f => f.Title, f => f.Contents)).Query("长沙科技"))).From(0).Size(15);


            //分词搜索(待完善)
            //QueryContainer query = new QueryStringQuery() { Query = key, DefaultOperator = Operator.And };
            //if (!String.IsNullOrEmpty(key))
            //{
            //    QueryContainer wholeWordQuery = new QueryStringQuery() { Query = key };
            //    query = query || wholeWordQuery;
            //} 
            //var searchResults = EsClient.Search<PolicyInfo>(s => s.Index("policyinfos").Query(query));

            //多条件精确匹配

            //QueryContainer termQuery = new TermQuery() { Field = "firstname", Value = "测试" };
            //QueryContainer wholeWordQuery = new TermQuery() { Field = "lastname", Value = "addddd" };
            //termQuery = (termQuery || wholeWordQuery);



            // 在原分值基础上 设置不同匹配的加成值 具体算法为lucene内部算法
            //searchDescriptor.Query(q => 
            //q.Term(t => t.Field(f => f.id).Value(5).Boost(4))||
            //q.Term(t => t.Field(f => f.id).Value(2).Boost(1)))
            //            .Size(5)
            //         .Sort(st => st.Descending(SortSpecialField.Score));

            //得分控制
            //searchDescriptor.Query(
            //    q => q.FunctionScore(f => f
            //              //查询区
            //              .Query(qq => qq.Term(t => t
            //                              .Field(fd => fd.id).Value(5))
            //                              ||
            //                           qq.Term(t => t
            //                            .Field(fd => fd.id).Value(1))
            //              )
            //              .Boost(1.0) //functionscore 对分值影响
            //              .BoostMode(FunctionBoostMode.Replace)//计算boost 模式 ；Replace为替换
            //              .ScoreMode(FunctionScoreMode.Sum) //计算score 模式；Sum为累加
            //                //逻辑区
            //              .Functions(fun => fun
            //                  .Weight(w => w.Weight(2).Filter(ft => ft
            //                      .Term(t => t
            //                              .Field(fd => fd.id).Value(5))))//匹配id +2
            //                  .Weight(w => w.Weight(1).Filter(ft => ft
            //                      .Term(t => t
            //                              .Field(fd => fd.id).Value(1))))//匹配id +1
            //              ))).Size(3000)
            //    .Sort(st => st.Descending(SortSpecialField.Score).Descending(dsc => dsc.id));

            //MoreLikeThisQueryDescriptor que=            
            //searchDescriptor.Query(q=>q.MoreLikeThis(g=>g.Fields(d=>d.Field(t=>t.Title)).Like(t=>t.Document(y=>y.Document(new PolicyInfo {  Title=key})))));


            //排序  根据得分排序
            searchDescriptor.Sort(x => x.Field("id", Nest.SortOrder.Descending));
            //searchDescriptor.Sort(x => x.Field("_score", Nest.SortOrder.Descending));
            var result = EsClient.Search<PolicyInfo>(searchDescriptor);
            return result.Documents.ToList();
        }

        public List<PolicyInfo> GetList()
        {
            List<PolicyInfo> policyinfos = new List<PolicyInfo>() {
                 new PolicyInfo{  id=1, Title="关于促进国防科技工业科技成果转化的若干意见", Desc="", Contents="为落实国家创新驱动发展战略和军民融合发展战略，促进国防科技工业科技成果的转化应用，激发国防科技工业相关单位及科技人员的创新创业热情，更好地履行支撑国防军队建设、推动科学技术进步、服务经济社会发展的职责，依据《中华人民共和国促进科技成果转化法》等法律法规，结合国防科技工业实际，提出本意见"},
              new PolicyInfo {  id=2, Title="国防科技重点实验室稳定支持科研管理暂行办法", Desc="", Contents="为进一步推进落实国家创新驱动发展战略和军民融合发展战略，加大国防科技基础研究领域创新力度，充分发挥国防科技重点实验室自主创新平台作用，赋予一线科研人员更多自主权，建立稳定规范的基础科研项目支持机制，国防科工局制定了《国防科技重点实验室稳定支持科研管理暂行办法》，现予印发，请遵照执行"},
                 new PolicyInfo {  id=3, Title="长沙高新区促进军民融合产业发展实施意见", Desc="", Contents="《长沙高新区促进军民融合产业发展实施意见》（简称《意见》）出炉，《意见》对高新区内工商注册和税务登记的军民融合企业、单位进行重点支持，包括具有或部分具有武器装备科研生产单位保密资格证、武器装备质量管理体系证、武器装备科研生产许可证、装备承制单位资格证（即“军工四证”）的民口企业，民品业务收入占企业总营业收入70%以上，承担军工协作配套科研生产及维修任务，以及提供军民融合领域第三方服务的企业、单位"},
                    new PolicyInfo {  id=4, Title="关于加快新一代人工智能产业发展推动国家智能制造中心建设的若干政策", Desc="", Contents="为进一步加速我市新一代人工智能产业发展，推动国家智能制造中心建设，根据《国务院关于印发新一代人工智能发展规划的通知》（国发〔2017〕35号）、《工业和信息化部关于印发促进新一代人工智能产业发展三年行动计划（2018—2020年）的通知》（工信部科〔2017〕315号）和《长沙建设国家智能制造中心三年行动计划（2018—2020）》（长办发〔2017〕23号），结合我市实际，特制定本政策"},
                       new PolicyInfo {  id=5, Title="长沙市建设创新创业人才高地的若干措施", Desc="", Contents="人才是经济社会发展的第一资源。长沙创建国家中心城市实现基本现代化，必须深入实施创新引领、开放崛起战略，始终坚持人才优先发展，统筹推进各类人才队伍建设，聚力打造创新创业人才高地，全面激发社会创造活力。根据《中共中央印发〈关于深化人才发展体制机制改革的意见〉的通知》（中发﹝2016﹞9号）、《中共湖南省委印发〈关于深化人才发展体制机制改革的实施意见〉的通知》（湘发﹝2016﹞27号）和省第十一次党代会、市第十三次党代会精神，结合我市实际，现提出如下措施"},
                       new PolicyInfo { id=6,Title="中国（长沙）跨境电子商务综合试验区实施方案",Desc="",Contents="为全面推进中国（长沙）跨境电子商务综合试验区（以下简称“长沙综试区”）建设，根据《国务院关于同意在北京等22个城市设立跨境电子商务综合试验区的批复》（国函〔2018〕93号）要求，制定本实施方案"},
                       new PolicyInfo { id=7,Title="国防科技重点实验室稳定支持科研管理暂行办法",Desc="",Contents="为进一步推进落实国家创新驱动发展战略和军民融合发展战略，加大国防科技基础研究领域创新力度，充分发挥国防科技重点实验室自主创新平台作用，赋予一线科研人员更多自主权，建立稳定规范的基础科研项目支持机制，国防科工局制定了《国防科技重点实验室稳定支持科研管理暂行办法》，现予印发，请遵照执行。"},
                       new PolicyInfo { id=8,Title="大众创业万众创新税收优惠政策指引",Desc="",Contents="推进大众创业、万众创新，是发展的动力之源，也是富民之道、公平之计、强国之策，截至2017年7月，我国针对创业就业主要环节和关键领域陆续推出了83项税收优惠措施，尤其是2013年以来，新出台了73项税收优惠，覆盖企业整个生命周期企业初创期，除了普惠式的税收优惠，重点行业的小微企业购置固定资产，特殊群体创业或者吸纳特殊群体就业（高校毕业生、失业人员、退役士兵、军转干部、随军家属、残疾人、回国服务的在外留学人员、长期来华定居专家等）还能享受特殊的税收优惠。同时，国家还对扶持企业成长的科技企业孵化器、国家大学科技园等创新创业平台、创投企业、金融机构、企业和个人等给予税收优惠，帮助企业聚集资金"},
                       new PolicyInfo { id=9,Title="产业技术基础公共服务平台建设管理暂行办法",Desc="",Contents="第一条 为了加快实施创新驱动发展战略，落实《中国制造2025》的任务要求,实施工业强基工程，保障产业创新发展和质量品牌提升，完善重点产业技术基础体系，优化资源配置，培育一批具备权威性、基础性、公益性、前瞻性的技术基础公共服务平台，制定本办法。"},
                       new PolicyInfo { id=10,Title="湖南省技术改造节能创新专项资金管理办法",Desc="",Contents="第一条 为推进工业结构调整和产业转型升级，促进企业 技术创新和节能降耗，进一步发挥财政资金的引导和激励作用， 根据《中华人民共和国预算法》、《中华人民共和国节约能源法》、 《国务院关于促进企业技术改造的指导意见》（国发〔2012〕44 号）、《国务院办公厅关于强化企业技术创新主体地位全面提升 企业创新能力的意见》（国办发〔2013〕8 号），制定本办法。第二条 本办法所称湖南省技术改造节能创新专项资金 （以下简称专项资金）是指省财政预算安排，用于支持企业技 术改造、推进工业节能降耗和资源综合利用、促进技术创新、 技术研发和产业技术成果转化的专项资金。三条 专项资金使用遵循以下原则："}
            };
            return policyinfos;
        }

    }
}
